/////////////////////////////////////////////////////////////////////////////
/**
 * \title Simulation of new Setup for transfer-reactions 
 *
 *  
 *  
 *  
 *
 *  \author Vinzenz Bildstein
 *
 **/
////////////////////////////////////////////////////////////////////////////

#include "G4RunManager.hh"

#include "G4UImanager.hh"
#include "G4UIterminal.hh"
#include "G4UItcsh.hh"

//detectors
#include "DetectorConstruction.hh"

// physics
#include "PhysicsList.hh"
#include "PrimaryGeneratorAction.hh"
#include "EventAction.hh"
#include "G4DecayTable.hh"
#include "G4BetaMinusDecayChannel.hh"

//histogramming
#include "HistoManager.hh"
#include "MiniBallHistoGenerator.hh"
#include "MiniBallRootGenerator.hh"
#include "SteppingAction.hh"

//radioactive sources
#include "MiniBallCobalt60Source.hh"
#include "MiniBallEuropium152Source.hh"

#ifdef G4VIS_USE
#include "VisManager.hh"
#endif

#include "Randomize.hh"

#include "Data.hh"

using namespace std;
using namespace CLHEP;


int main(int argc, char* argv[]) 
{
  //data class for parameters etc.
  Data* data = new Data(argc,argv);

  // choose the Random engine
  HepRandom::setTheEngine(new RanecuEngine);
  G4long seed;
  seed = time(0);
  HepRandom::setTheSeed(seed);

  // Construct the default run manager
  G4RunManager* runManager = new G4RunManager;

  // initalize histogramming
  MiniBallRootGenerator* histoGen = NULL;
  histoGen = new MiniBallRootGenerator(data->Filename,5);

  if(histoGen == NULL)
    {
      cerr<<"Error, couldn't find histoGen"<<endl;
      return 1;
    }
  
  HistoManager* histoManager = new HistoManager(histoGen, data);

  //construct detectors and target
  DetectorConstruction* detector = new DetectorConstruction(histoManager, data);

  runManager->SetUserInitialization(detector);
  runManager->SetUserInitialization(new PhysicsList());

  // visualization manager
#ifdef G4VIS_USE
  G4VisManager* visManager = new VisManager;
  visManager->Initialize();
#endif

  // set user action classes
  PrimaryGeneratorAction* Generator = NULL;
  if(data->EuropiumSource)
    {
      runManager->SetUserAction(new MiniBallEuropium152Source());
      cout<<"using Europium152 source"<<endl;
    }
  else if(data->CobaltSource)
    {
      runManager->SetUserAction(new MiniBallCobalt60Source());
      cout<<"using Cobalt60 source"<<endl;
    }
  else
    {
      Generator = new PrimaryGeneratorAction(histoManager, data);
      runManager->SetUserAction(Generator);
    }

  runManager->SetUserAction(new EventAction(histoManager, data));
  runManager->SetUserAction(new SteppingAction(histoManager, data));
  //  runManager->SetUserAction(new ExN04StackingAction);

  // initialize G4 kernel
  runManager->Initialize();

  // set resolution of detectors
  histoManager->SetAllSigma(CORE, 2.4*keV);
  histoManager->SetAllSigma(ALL_SEG, 1.9*keV);

  // set energy unit to keV
  histoManager->SetEnergyUnit(keV);

  if(data->VerboseLevel > 1){
    histoManager->Status();
  }

  //run simulation
  data->run(runManager);

  if(data->CobaltSource || data->EuropiumSource)//if a source was selected the data->EventNumber isn't automatically increased
    {
      data->EventNumber = data->NoE;
    }

  if(!data->Efficiency)
    {
      int IntegerEvents, IntegerDetectedEvents, BeamParticles;
      IntegerEvents = (int)data->EventNumber;
      IntegerDetectedEvents = (int)data->DetectedEventNumber;
      if(Generator != NULL)
	{
	  Generator->BeamParticles();
	}
      BeamParticles = (int)(data->BeamParticles);
      histoManager->cl->Branch("Events",&IntegerEvents,"EventNumber/I");
      histoManager->cl->Branch("DetectedEvents",&IntegerDetectedEvents,"DetectedEventNumber/I");
      histoManager->cl->Branch("BeamParticles",&BeamParticles,"BeamParticles/I");
      histoManager->cl->Fill();
      histoManager->cl->Write("",TObject::kOverwrite);
      
      cout<<"Done with simulation of "<<IntegerEvents<<" events. "<<IntegerDetectedEvents<<" events were detected (= "<<BeamParticles<<" beam particles)."<<endl;
      cout<<"detected "<<data->HitsInFBarrel<<" hits in forward and "<<data->HitsInBBarrel<<" in backward barrel,"<<endl
	  <<"         "<<data->HitsInFCD<<" hits in forward and "<<data->HitsInBCD<<" in backward cd,"<<endl
	  <<"     and "<<data->HitsInMiniball<<" hits in Miniball!"<<endl;
    cout << "Theta_cm_min: " << data->ThetaCmMin << ",	Theta_cm_Max: " << data->ThetaCmMax << endl; 
	 }
  else
    {
      cout<<"Done with simulation of "<<data->EventNumber<<" events."<<endl;
      for(int i=0;i<8;i++)
	{
	  cout<<"\t"<<data->GammaCounter[i]<<" events of energy "<<i<<" were simulated."<<endl;
	}
    }

  //cout<<"1/(mg/cm2) = "<<1/(mg/cm2)<<", 1/mm = "<<1/mm<<", 1/mg = "<<1/mg<<", 1/(1/cm2) = "<<1/(1/cm2)<<endl;
  
  // job termination
  if(data->VerboseLevel > 0)
    {
      cout<<"deleting visManager ... ";
    }
#ifdef G4VIS_USE
  delete visManager;
#endif

  if(data->VerboseLevel > 0)
    {
      cout<<"deleting runManager ... ";
    }
  delete runManager;
  if(data->VerboseLevel > 0)
    {
      cout<<"deleting histoManager ... ";
    }
  delete histoManager;
  
  if(data->VerboseLevel > 0)
    {
      cout<<"closing histoGen ... ";
    }
  histoGen->Close();
  if(data->VerboseLevel > 0)
    {
      cout<<"deleting histoGen ... ";
    }
  delete histoGen;
  if(data->VerboseLevel > 0)
    {
      cout<<"done"<<endl;
    }

  return 0;
}

